//-----------------------------------------------------------------------------
// File: Workspace.cs
//
// Copyright (c) Dmitry Shuklin. All rights reserved.
//-----------------------------------------------------------------------------
using System;
using System.ComponentModel;
using System.Collections;
using System.Diagnostics;

namespace ObjectiveDraw.Platform
{
	/// <summary>
	/// Summary description for Workspace.
	/// </summary>
	public class Workspace //--: Cerebrum.Integrator.GenericComponent , IDrawerComponent
	{

		public static bool ConfigureComponent(IDrawerComponent component, string messageName, object descriptor)
		{
			bool r = true;
			/*--
			//Cerebrum.Integrator.IComponent cfg = component.SystemContext.AcquireComponent(KnownDrawerComponents.Configurator) as Cerebrum.Integrator.IComponent;
			Cerebrum.Integrator.UiCommand cmd = component.SystemContext.PrimaryWindow.GetCommand(commandId);
			Configuration.ConfigureInstanceEventArgs ea = new Configuration.ConfigureInstanceEventArgs(cmd, component, null);
			//cfg.Execute(component, ea);
			cmd.FireExecuting(component, ea);
			return (ea.Result is System.Windows.Forms.DialogResult)?((System.Windows.Forms.DialogResult)ea.Result == System.Windows.Forms.DialogResult.OK):false;
		--*/
			Cerebrum.Integrator.DomainContext c = (Cerebrum.Integrator.DomainContext)component.DomainContext;
			Cerebrum.Windows.Forms.Application app = c.Application as Cerebrum.Windows.Forms.Application;
			Cerebrum.ObjectHandle msgHnd = Cerebrum.Management.Utilites.ResolveHandle(app.MasterContext, "Messages", "Name", messageName);
			Cerebrum.Windows.Forms.Reflection.UiServiceDescriptor cfg = (Cerebrum.Windows.Forms.Reflection.UiServiceDescriptor)Workspace.InitializeInstance(app.MasterContext, KnownDrawerComponents.DrawerConfigurator, null);
			using(Cerebrum.IConnector message = app.MasterContext.AttachConnector(msgHnd))
			{
				r = cfg.CommandActivated(message, null, new Cerebrum.Desktop.Configuration.ConfigureInstanceEventArgs(component, descriptor));
			}


			ObjectiveDraw.Platform.Application _ta = null;
			Cerebrum.ObjectHandle _happ = Cerebrum.ObjectHandle.Null;

			ObjectiveDraw.Platform.DrawerDocument d = c as ObjectiveDraw.Platform.DrawerDocument;
			if(d!=null)
			{
				_ta = d.DrawerApplication;
				_happ = d.ObjectHandle;
			}

			if(component is ObjectiveDraw.Platform.Application)
			{
				_ta = component as ObjectiveDraw.Platform.Application;
			}

			if(_ta!=null)
			{
				//System.Diagnostics.Trace.WriteLine("t1 = " + System.DateTime.Now.ToString());

				SerializationContext sc = new SerializationContext(_ta, Cerebrum.SerializeDirection.Save, new System.Collections.Hashtable());
				using(Cerebrum.IComposite connectorApp = _ta.DomainContext.AttachConnector(_ta.ObjectHandle))
				{
					ObjectiveDraw.Platform.Serialization.FallbackChain chainApp = new ObjectiveDraw.Platform.Serialization.FallbackChain(null, connectorApp as Cerebrum.IContainer);
					if(_happ != Cerebrum.ObjectHandle.Null && d!=null)
					{
						using(Cerebrum.IComposite connector = c.AttachConnector(_happ))
						{
							d.Serialize(chainApp.CreateDependent(connector as Cerebrum.IContainer), sc);
						}
					}
					else
					{
						_ta.Serialize(chainApp, sc);
					}
				}
				//System.Diagnostics.Trace.WriteLine("t2 = " + System.DateTime.Now.ToString());
			}
			return r;
		}

		public static object CreateInstanceByTypeName(Cerebrum.Integrator.DomainContext model, string typeName)
		{
			Cerebrum.ObjectHandle instanceHandle = Cerebrum.Management.Utilites.ResolveHandle(model, "Types", "Name", typeName);
			return Cerebrum.Integrator.Utilites.CreateInstance(model.Workspace, instanceHandle, null);
		}
		public static object CreateInstanceByTypeName(Cerebrum.Integrator.DomainContext model, string typeName, Cerebrum.Integrator.DomainContext owner, Cerebrum.ObjectHandle objectHandle, ObjectiveDraw.Platform.Serialization.FallbackChain storage, SerializationContext context)
		{
			ObjectiveDraw.Platform.Application app = ObjectiveDraw.Platform.Application.FromComponent(model);
			if(app!=null && app.m_CompBackTypeMap!=null)
			{
				if(app.m_CompBackTypeMap.ContainsKey(typeName))
				{
					typeName = Convert.ToString(app.m_CompBackTypeMap[typeName]);
				}
			}

			Cerebrum.ObjectHandle typeIdHandle = Cerebrum.Management.Utilites.ResolveHandle(model, "Types", "Name", typeName);
			object instance = Cerebrum.Integrator.Utilites.CreateInstance(model.Workspace, typeIdHandle, null);
			Cerebrum.IComponent component = instance as Cerebrum.IComponent;
			if(component!=null)
			{
				component.SetConnector(Cerebrum.SerializeDirection.None, new Cerebrum.Runtime.SurrogateComposite(owner.Workspace));
			}
			ObjectiveDraw.Platform.IDrawerComponent tc = instance as ObjectiveDraw.Platform.IDrawerComponent;
			if(tc!=null)
			{
				tc.TypeName = typeName;
				tc.ObjectHandle = objectHandle;
				tc.Serialize(storage, context);
			}
			return instance;
		}
		public static object InitializeInstance(Cerebrum.Integrator.DomainContext c, string typeName, SerializationContext context)
		{
			return ObjectiveDraw.Platform.Workspace.CreateInstanceByTypeName((c.Application as Cerebrum.Integrator.Application).MasterContext, typeName, c, Cerebrum.ObjectHandle.Null, null, context);
		}

		public static object DeserializeInstance(Cerebrum.Integrator.DomainContext c, Cerebrum.ObjectHandle typeNameAttrHnd, ObjectiveDraw.Platform.Serialization.FallbackChain owner, SerializationContext context, Cerebrum.ObjectHandle objectHandle)
		{
			if(context.ObjectsGraph.ContainsKey(objectHandle))
			{
				SerializationGraphEntry e = ((SerializationGraphEntry)context.ObjectsGraph[objectHandle]);
				if(!e.Serialized)
				{
					e.Serialized = true;
					ObjectiveDraw.Platform.IDrawerComponent tc = e.Instance as ObjectiveDraw.Platform.IDrawerComponent;
					if(tc!=null)
					{
						using(Cerebrum.IConnector connector = c.AttachConnector(objectHandle))
						{
							Cerebrum.IContainer container = (Cerebrum.IContainer)connector;
							tc.Serialize(owner.CreateDependent(container), context);
						}
					}
				}
				return e.Instance;
			}
			using(Cerebrum.IConnector connector = c.AttachConnector(objectHandle))
			{
				Cerebrum.IContainer container = (Cerebrum.IContainer)connector;
				string typeName = Convert.ToString(Cerebrum.Integrator.Utilites.ObtainComponent(container, typeNameAttrHnd));
				object component = ObjectiveDraw.Platform.Workspace.CreateInstanceByTypeName((c.Application as Cerebrum.Integrator.Application).MasterContext, typeName, c, objectHandle, owner.CreateDependent(container), context);
				context.ObjectsGraph[objectHandle] = new SerializationGraphEntry(component, true);
				/*ObjectiveDraw.Platform.IDrawerComponent tc = component as ObjectiveDraw.Platform.IDrawerComponent;
				if(tc!=null)
				{
					tc.ObjectHandle = objectHandle;
					tc.Serialize(owner.CreateDependent(container), context);
				}*/
				return component;
			}
		}
		public static void SerializeInstance(Cerebrum.Integrator.DomainContext c, Cerebrum.ObjectHandle typeNameAttrHnd, ObjectiveDraw.Platform.Serialization.FallbackChain owner, SerializationContext context, ObjectiveDraw.Platform.IDrawerComponent component, string tableName)
		{
			if(component==null) return;
			if(component.ObjectHandle==Cerebrum.ObjectHandle.Null)
			{
				using(Cerebrum.Data.TableView view = Cerebrum.Management.Utilites.GetView(c, tableName))
				{
					Cerebrum.Data.ComponentItemView item = view.AddNew();
					component.ObjectHandle = item.ObjectHandle;
				}
			}
			else
			{
				if(context.ObjectsGraph.ContainsKey(component.ObjectHandle))
				{
					return;
				}
			}
			context.ObjectsGraph[component.ObjectHandle] = component;
			using(Cerebrum.IConnector connector = c.AttachConnector(component.ObjectHandle))
			{
				Cerebrum.IContainer container = (Cerebrum.IContainer)connector;
				Cerebrum.Integrator.Utilites.UpdateComponent(container, typeNameAttrHnd, component.TypeName);
				component.Serialize(owner.CreateDependent(container), context);
			}
		}
		/*--
		public const string SystemComponentId = "TradingPlatform.Workspace";

		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		public Workspace(System.ComponentModel.IContainer container)
		{
			///
			/// Required for Windows.Forms Class Composition Designer support
			///
			container.Add(this);
			InitializeComponent();

			//
			// TODO: Add any constructor code after InitializeComponent call
			//
		}

		public Workspace()
		{
			///
			/// Required for Windows.Forms Class Composition Designer support
			///
			InitializeComponent();

			//
			// TODO: Add any constructor code after InitializeComponent call
			//
		}

		/// <summary> 
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}


		#region Component Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			components = new System.ComponentModel.Container();
		}
		#endregion
	
		protected Cerebrum.Integrator.RuntimeDatabase m_WorkspaceDatabase;

		public Cerebrum.Integrator.SystemDatabase WorkspaceDatabase
		{
			get
			{
				return m_WorkspaceDatabase;
			}
		}

		public void Attach()
		{
			if(!m_DomainContext.FallbackDatabases.Contains(this.m_WorkspaceDatabase))
			{
				m_DomainContext.FallbackDatabases.Add(this.m_WorkspaceDatabase);
			}
		}

		public void Restore()
		{
			this.Serialize(new SerializationContext(this, SerializationContextMotive.Restoring), Cerebrum.SerializeDirection.Take);
			this.m_DomainContext.PrimaryWindow.Text = this.Name;
		}

		public void Suspend()
		{
			this.Serialize(new SerializationContext(this, SerializationContextMotive.Suspending), Cerebrum.SerializeDirection.Take);
		}


		public void Detach()
		{
			if(m_DomainContext.FallbackDatabases.Contains(this.m_WorkspaceDatabase))
			{
				m_DomainContext.FallbackDatabases.Remove(this.m_WorkspaceDatabase);
			}
		}

		public static object LoadVariable(ObjectiveDraw.Platform.IDrawerComponent component, string variableId, object value)
		{
			System.Collections.Hashtable variables = component.Variables;

			if(variables!=null && variables.ContainsKey(variableId))
			{
				return variables[variableId];
			}
			object v = null;
			if(v==null) v = value;
			if(variables!=null) variables[variableId] = v;
			return v;
			//--return LoadVariable(component, variableId, value, new SerializationContext(component, SerializationContextMotive.Persisting));
		}
		
		public static object LoadVariable(ObjectiveDraw.Platform.IDrawerComponent component, string variableId, object value, SerializationContext context)
		{
			System.Collections.Hashtable variables = component.Variables;

			if(variables!=null && variables.ContainsKey(variableId))
			{
				return variables[variableId];
			}
			object v = null;
			bool fallback = false;
			do
			{
				v = component.SystemContext.GetSystemVariable(component.InstanceId, variableId, context);
				if(v!=null) 
				{
					if(fallback)
					{
						System.Collections.Hashtable vars = component.Variables;
						if(vars!=null) vars[variableId] = v;
					}
					break;
				}
				component = component.Master;
				fallback = true;
			} 
			while(component!=null);

			if(v==null) v = value;
			if(variables!=null) variables[variableId] = v;
			return v;
		}

		public static object LoadVariable(bool fallback, ObjectiveDraw.Platform.IDrawerComponent component, string variableId)
		{
			return LoadVariable(fallback, component, variableId, new SerializationContext(component.Master, SerializationContextMotive.Persisting));
		}
		public static object LoadVariable(bool fallback, ObjectiveDraw.Platform.IDrawerComponent component, string variableId, SerializationContext context)
		{
			do
			{
				object v = component.SystemContext.GetSystemVariable(component.InstanceId, variableId, context);
				if(v!=null) return v;
				component = component.Master;
			} 
			while(fallback && component!=null);
			return null;
		}

		public static void SaveVariable(ObjectiveDraw.Platform.IDrawerComponent component, string variableId, object value)
		{
			SaveVariable(component, variableId, value, new SerializationContext(component.Master, SerializationContextMotive.Persisting));
		}
		public static void SaveVariable(ObjectiveDraw.Platform.IDrawerComponent component, string variableId, object value, SerializationContext context)
		{
			if(CheckVariable(component.Master, variableId, value))
			{
				Cerebrum.Integrator.SystemDatabase _WorkspaceDatabase = component.Workspace.m_WorkspaceDatabase;
				Cerebrum.Integrator.SystemDatabase.InstancesRow rw = _WorkspaceDatabase.Instances.FindByInstanceId(component.InstanceId);
				if(rw==null)
				{
					rw = _WorkspaceDatabase.Instances.NewInstancesRow();
					rw.InstanceId = component.InstanceId;
					rw.ComponentId = component.ComponentId;
					_WorkspaceDatabase.Instances.AddInstancesRow(rw);
				}
				component.SystemContext.SetSystemVariable(component.InstanceId, variableId, value, context);
			}
			else
			{
				component.SystemContext.DelSystemVariable(component.InstanceId, variableId, context);
			}
			System.Collections.Hashtable variables = component.Variables;
			if(variables!=null) 
			{
				object v = variables[variableId];
				if(v != null && v != value)
					variables[variableId] = value;
			}
		}
		public static void KillVariable(ObjectiveDraw.Platform.IDrawerComponent component, string variableId, SerializationContext context)
		{
			component.SystemContext.DelSystemVariable(component.InstanceId, variableId, context);
		}
		public static bool CheckVariable(ObjectiveDraw.Platform.IDrawerComponent component, string variableId, object value)
		{
			while(component!=null)
			{
				object v = component.Variables==null?null:component.Variables[variableId];
				if(v!=null)
				{
					return !v.Equals(value);
				}
				component = component.Master;
			} 
			return true;
		}

		protected string m_FullFileName;
		public string FullFileName
		{
			get
			{
				return m_FullFileName;
			}
			set
			{
				m_FullFileName = value;
			}
		}

		public string Name
		{
			get
			{
				return System.IO.Path.GetFileNameWithoutExtension(m_FullFileName);
			}
		}
		protected string m_InstanceId;

		#region IDrawerComponent Members

		ObjectiveDraw.Platform.Workspace ObjectiveDraw.Platform.IDrawerComponent.Workspace
		{
			get
			{
				return this;
			}
		}

		public string InstanceId
		{
			get
			{
				return m_InstanceId;
			}
			set
			{
				m_InstanceId = value;
			}
		}

		public IDrawerComponent Master
		{
			get
			{
				return TradingPlatform.Application.FromComponent(this);
			}
		}

		public System.Collections.Hashtable Variables
		{
			get
			{
				return m_Variables;
			}
		}
		#endregion

		protected System.Collections.Hashtable m_Variables = new Hashtable();


		public void Serialize(object context, Cerebrum.SerializeDirection operation)
		{
			if(Cerebrum.SerializeDirection.Save==operation)
			{
				System.Collections.ArrayList windows = GetWindows(false);
				SaveVariable(this, KnownDrawerVariables.ComplexObjectDrawerWindow, windows.Count);
				int i = 0;
				foreach(IDrawerComponent component in windows)
				{
					SaveVariable(this, KnownDrawerVariables.ComplexObjectDrawerWindow + "." + i, component,  new SerializationContext(this, ((SerializationContext)context).Motive));
					i++;
				}
			}
			if(Cerebrum.SerializeDirection.Load==operation)
			{
				int c = (int)LoadVariable(false, this, KnownDrawerVariables.ComplexObjectDrawerWindow, (SerializationContext)context);
				for(int i=0;i<c;i++)
				{
					LoadWindow(KnownDrawerVariables.ComplexObjectDrawerWindow + "." + i);
				}
			}
			if(Cerebrum.SerializeDirection.Init==operation)
			{
				//m_WorkspaceDatabase = new Cerebrum.Integrator.RuntimeDatabase();
#warning "System.Guid.NewGuid().ToString()"
				m_InstanceId = System.Guid.NewGuid().ToString().ToUpper();

				m_WorkspaceDatabase.Instances.AddInstancesRow(this.InstanceId, this.ComponentId);
				m_WorkspaceDatabase.AcceptChanges();
			}
			if(Cerebrum.SerializeDirection.Take==operation)
			{
				System.Collections.ArrayList windows = GetWindows(true);
				//int i = 0;
				foreach(IDrawerComponent component in windows)
				{
					component.Serialize(new SerializationContext(this, ((SerializationContext)context).Motive), operation);
					//i++;
				}
			}
		}

		public void NewDatabase()
		{
			m_WorkspaceDatabase = new Cerebrum.Integrator.RuntimeDatabase();
		}

		public void LoadFrom(System.IO.Stream stream)
		{
			System.Runtime.Serialization.IFormatter formatter;
			formatter = (System.Runtime.Serialization.IFormatter) new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

			m_InstanceId = Convert.ToString(formatter.Deserialize(stream));

			NewDatabase();

			m_WorkspaceDatabase.ReadXml(stream);
			m_WorkspaceDatabase.AcceptChanges();
		}

		public void SaveTo(System.IO.Stream stream)
		{
			System.Runtime.Serialization.IFormatter formatter;
			formatter = (System.Runtime.Serialization.IFormatter) new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
        
			formatter.Serialize(stream, m_InstanceId);

			m_WorkspaceDatabase.AcceptChanges();
			m_WorkspaceDatabase.WriteXml(stream);
		}

		public System.Collections.ArrayList GetWindows(bool resurrect)
		{
			System.Collections.ArrayList list = new ArrayList();;
			System.Data.DataView view = new System.Data.DataView(m_WorkspaceDatabase.Instances, "ComponentId='" + GraphChartDevice.SystemComponentId + "'", "",  System.Data.DataViewRowState.CurrentRows);
			foreach(System.Data.DataRowView row in view)
			{
				Cerebrum.Integrator.RuntimeDatabase.InstancesRow rw = row.Row as Cerebrum.Integrator.RuntimeDatabase.InstancesRow;
				if(rw!=null)
				{
					object w = null;
					if(!rw.IsRuntimeObjectNull())
					{
						w = rw.RuntimeObject as TradingPlatform.GraphChartDevice;
					}
					if(w==null && resurrect)
					{
						w = this.m_DomainContext.GetSystemInstance(rw.InstanceId, new SerializationContext(this, SerializationContextMotive.Persisting));
					}
					if(w!=null)
					{
						list.Add(w);
					}
				}
			}
			return list;
		}

		public Cerebrum.Integrator.ISerializable AddNewWindow()
		{
			GraphChartDevice component = m_DomainContext.NewSystemInstance(TradingPlatform.GraphChartDevice.SystemComponentId, new SerializationContext(this, SerializationContextMotive.Persisting)) as GraphChartDevice;
			//(m_WorkspaceDatabase.Instances.AddInstancesRow(component.InstanceId, component.ComponentId) as Cerebrum.Integrator.RuntimeDatabase.InstancesRow).RuntimeObject = component;

			if(component!=null)
				component.Execute(this, new Cerebrum.Integrator.InvokeCommandEventArgs(m_DomainContext.PrimaryWindow.GetCommand("show")));
			return component;
		}

		public Cerebrum.Integrator.ISerializable LoadWindow(string variableId)
		{
			GraphChartDevice component = LoadVariable(false, this, variableId, new SerializationContext(this, SerializationContextMotive.Persisting)) as GraphChartDevice;

			//if(component!=null)
			//	component.Execute(this, new Cerebrum.Integrator.InvokeCommandEventArgs(m_DomainContext.PrimaryWindow.GetCommand("show")));
			return component;
		}--*/
	}

}
